package switchviz.recording;

import org.apache.log4j.Logger;

import switchviz.core.signal.ISignal;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;


public class Replay
{
    //~ Static fields/initializers -----------------------------------------------------------------

    private static Logger logger = Logger.getLogger(Replay.class);

    //~ Instance fields ----------------------------------------------------------------------------

    private RecordDataModel _recordDataModel = null;
    private List<ReplayFileAdapter> _signals = new ArrayList<ReplayFileAdapter>();
    private long _position;
    private long _delay;
    private boolean running = false;
    private int _countSignals = 0;
    private int _countFiles = 0;

    //~ Constructors -------------------------------------------------------------------------------

    public Replay(RecordDataModel recordDataModel)
    {
        _recordDataModel = recordDataModel;
        _position = recordDataModel.getRecStart();

        createReplayFileAdapter();
    }

    //~ Methods ------------------------------------------------------------------------------------

    public void add(ISignal signal)
    {
        Iterator<ReplayFileAdapter> iter = _signals.iterator();

        while (iter.hasNext())
        {
            ReplayFileAdapter signals = iter.next();

            if (signals.getSignalName().equals(signal.getAliasName() + "_" + signal.getPort()))
            {
                if (logger.isInfoEnabled())
                {
                    logger.info("Adding signal '" + signal.getAliasName() + " (port=" +
                        signal.getPort() + ")' to file.");
                }

                signals.addSignal(signal);
                ++_countSignals;
            }
        }
    }

    public void start()
    {
        running = true;

        _delay = System.currentTimeMillis() - _position;
    }

    public void pause()
    {
        running = false;
    }

    public void stop()
    {
        running = false;

        _position = _recordDataModel.getRecStart();

        Iterator<ReplayFileAdapter> iter = _signals.iterator();

        while (iter.hasNext())
        {
            ReplayFileAdapter signals = iter.next();

            try
            {
            	signals.restart();
                signals.reset();
            }
            catch (IOException e)
            {
                logger.error(e.getMessage());
            }
        }
    }

    public void jumpTo(int position)
    {
        boolean run = running;
    	
        if (run)
        	pause();
        
        _position = _recordDataModel.getRecStart() + position;

        Iterator<ReplayFileAdapter> iter = _signals.iterator();

        while (iter.hasNext())
        {
            ReplayFileAdapter signals = iter.next();

            try
            {
                signals.restart();
            }
            catch (IOException e)
            {
                logger.error(e.getMessage());
            }
        }

        if (run)
        	start();
    }

    public void refresh()
    {
        if (running)
        {
            _position = System.currentTimeMillis() - _delay;

            if (_position > _recordDataModel.getRecEnd())
            {
                stop();

                return;
            }

            Iterator<ReplayFileAdapter> iter = _signals.iterator();

            while (iter.hasNext())
            {
                ReplayFileAdapter signals = iter.next();

                try
                {
                    signals.read(_position);
                }
                catch (IOException e)
                {
                    logger.error(e.getMessage());
                }
            }
        }
    }

    private void createReplayFileAdapter()
    {
        String[] filenames = _recordDataModel.getFolder().list();
        File[] files = _recordDataModel.getFolder().listFiles();

        for (int i = 0; i < filenames.length; i++)
            if (files[i].isFile() && !filenames[i].contains("."))
            {
                _signals.add(new ReplayFileAdapter(filenames[i], files[i]));
            }
    }

    public void open()
    {
        List<ReplayFileAdapter> delete = new LinkedList<ReplayFileAdapter>();

        Iterator<ReplayFileAdapter> iter = _signals.iterator();

        while (iter.hasNext())
        {
            ReplayFileAdapter signals = iter.next();

            try
            {
                if ((signals.getAttachedSignals() > 0) && signals.open())
                {
                    _countFiles++;
                }
                else
                {
                    delete.add(signals);
                }

                if (logger.isInfoEnabled())
                {
                    logger.info("Open file: " + signals.getFileName());
                }
            }
            catch (FileNotFoundException e)
            {
                logger.error(e.getMessage());
            }
        }

        Iterator<ReplayFileAdapter> iter2 = delete.iterator();

        while (iter2.hasNext())
            _signals.remove(iter2.next());
    }

    public void close() throws IOException
    {
        Iterator<ReplayFileAdapter> iter = _signals.iterator();

        while (iter.hasNext())
        {
            ReplayFileAdapter signals = iter.next();

            signals.close();
        }
    }

    public int getFileListSize()
    {
        return _countFiles;
    }

    public int getSignalListSize()
    {
        return _countSignals;
    }

    public int getLength()
    {
        return (int) (_recordDataModel.getRecEnd() - _recordDataModel.getRecStart());
    }

    public int getPosition()
    {
        return (int) (_position - _recordDataModel.getRecStart());
    }
    
    public String toString()
    {
    	return _recordDataModel.toString() + " from " + _recordDataModel.getSwitchName();
    }
}
